package com.apes.autoparts.supplier.inheart;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.supplier.platform.SupplierPlatformItem;
import com.apes.autoparts.supplier.platform.SupplierPlatformItemRepository;
import com.apes.autoparts.supplier.todo.SupplierPlatformTodoService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.CronExpression;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by lishikun on 2021/4/19 15:57
 */
@Service("inHeartService")
public class InHeartService<T, R> extends InHeartApi<T, R> {

    @Autowired
    private SupplierPlatformItemRepository supplierPlatformItemRepository;
    @Autowired
    private InHeartDao inHeartDao;
    @Autowired
    SequenceService sequenceService;
    @Autowired
    private SupplierPlatformTodoService todoService;
    JSONObject allkcKey;
    // 重点更新字段
    private final List<String> importantFields = Arrays.asList("pjbrand", "pjfactory", "pjcode");

    public void getToken(SimpleRequest request) {
        allkcKey = super.getAllkcKey(supplierPlatformItemRepository.findOne(request.getJO().getString("id")));
    }

    public void handHeap(SimpleRequest request) {
        JSONObject jo = request.getJO();
        JSONArray jsonArray = jo.getJSONArray("data");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(jo.getString("supplierPlatformItemId"));

        List<String> pjid = jsonArray.stream().map(v -> {
            JSONObject json = (JSONObject) v;
            return json.getString("pjid");
        }).collect(Collectors.toList());
        JSONObject param = new JSONObject();
        // 获取缓存表的配件id
        param.put("pjids", pjid);
        param.put("supplierPlatformItemId", supplierPlatformItem.getId());
        JSONArray inHearts = pjid.size() != 0 ? inHeartDao.findInHearts(param) : new JSONArray();
        Map map = new HashMap();
        for (Object o : inHearts) {
            JSONObject json = (JSONObject) o;
            map.put(json.getString("PJID"), json);
        }

        // 获取属于新建的数据
        JSONArray createJsonArray = jsonArray.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("pjid")) == null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));

        // 获取属于更新的数据
        JSONArray updateJsonArray = jsonArray.stream().filter(v -> {
            JSONObject json = (JSONObject) v;
            if (map.get(json.getString("pjid")) != null)
                return true;
            return false;
        }).collect(Collectors.toCollection(JSONArray::new));
        saveUpdateData(updateJsonArray, supplierPlatformItem, map);
        saveCreateData(createJsonArray, supplierPlatformItem);
        if(request.getJO().get("lastData") != null &&
                request.getJO().getBooleanValue("lastData") &&
                "synTotal".equals(request.getJO().getString("action")))
            deleteData(supplierPlatformItem);
    }

    private void deleteData(SupplierPlatformItem supplierPlatformItem) {
        List condition = new ArrayList();
        condition.add(MapUtil.mapper("field","id", "operator", "EQ", "value", "auto.supplierPlatform.synTotalTaskInHeart"));
        List list = ((Page<Object>)SpringManager.getBean(DomainService.class).invoke("schedule.task.findAll",
                MapUtil.mapper("condition", condition, "size", 20, "page", 0))).getContent();
        if (list == null || list.size() == 0) return;
        Map task = MapUtil.mapped(list.get(0));
        List<Map> cronExpression = inHeartRepository.findBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(), getHour(task.get("cronExpression").toString()) * 2);
        if (cronExpression.size() == 0) return;
        List<Map> newList= new ArrayList<>();
        for (Map map : cronExpression) {
            Map newMap = new HashMap(map);
            newMap.put("pjid", newMap.get("pjid"));
            newList.add(newMap);
        }
        try {
            todos(JSONArray.parseArray(JSON.toJSONString(newList)), supplierPlatformItem, "delete", new HashMap());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        inHeartRepository.deleteBySupplierPlatformItemAndNotUpdate(supplierPlatformItem.getId(),
                getHour(task.get("cronExpression").toString()) * 2);
    }

    /**
     * 保存属于创建的数据,并推送待办
     * @param jsonArray
     * @param supplierPlatformItem
     */
    private void saveCreateData(JSONArray jsonArray, SupplierPlatformItem supplierPlatformItem) {
        List<InHeart> inHearts = JSONArray.parseArray(jsonArray.toString(), InHeart.class);
        for (InHeart inHeart : inHearts) {
            inHeart.setSupplierPlatformItem(supplierPlatformItem);
        }

        todos(jsonArray, supplierPlatformItem,"create" , new HashMap<>());
        inHeartRepository.saveAll(inHearts);
    }



    /***
     * 保存属于更新的数据和推送待办
     * @param jsonArray
     * @param supplierPlatformItem
     * @param oldInHearts
     */
    private void saveUpdateData(JSONArray jsonArray, SupplierPlatformItem supplierPlatformItem, Map oldInHearts) {
        List<InHeart> inHearts = new ArrayList<>();
        JSONArray importantAttribute = new JSONArray();
        JSONArray update = new JSONArray();
        for (Object o : jsonArray) {
            JSONObject inHeart = (JSONObject) o;
            JSONObject oldInHeart = (JSONObject) oldInHearts.get(inHeart.getString("pjid"));
            InHeart heart = inHeartRepository.findOne(oldInHeart.getString("ID"));
            jsonToInHeart(inHeart, heart);
            if (checkImportantUpdate(inHeart, oldInHeart))
                importantAttribute.add(inHeart);
            else {
                update.add(inHeart);
            }
            inHearts.add(heart);
        }
        todos(importantAttribute, supplierPlatformItem,"importUpdate", oldInHearts);
        todos(update, supplierPlatformItem,"update", oldInHearts);
        inHeartRepository.save(inHearts);
    }

    /***
     * TODO
     * 批量推送待办
     * @param
     * @param supplierPlatformItem
     * 新用心数据，供应商，属性，老用心数据
     */
    private void todos(JSONArray newInHearts, SupplierPlatformItem supplierPlatformItem, String property, Map oldInHearts) {
        if (newInHearts.size() == 0 ) return;

        JSONObject param = new JSONObject();
        param.put("property", property);
        param.put("supplierPlatformItemId", supplierPlatformItem.getId());
        List<JSONObject> collect = newInHearts.stream().map(o -> {
            JSONObject newInHeart = (JSONObject) o;
            JSONObject oldInHeart = (JSONObject) oldInHearts.get(newInHeart.getString("pjid"));
            JSONObject todo =  new JSONObject();
            JSONObject supplierItem = new JSONObject();
            supplierItem.put("id", supplierPlatformItem.getId());
            todo.put("source", String.valueOf(Math.abs(newInHeart.getIntValue("pjid"))));
            todo.put("supplierPlatformItem", supplierItem);
            todo.put("oldBrandName", oldInHeart != null ? oldInHeart.getString("PJBRAND") : "");
            todo.put("brandName", newInHeart.getString("pjbrand"));
            todo.put("oldOriginPlace",oldInHeart != null ? oldInHeart.getString("PJFACTORY") :"");
            todo.put("originPlace", newInHeart.getString("pjfactory"));
            todo.put("oldPartCode", oldInHeart != null ? oldInHeart.getString("PJCODE") : "");
            todo.put("partCode", newInHeart.getString("pjcode"));
            todo.put("oldPartCodeName", oldInHeart != null ? oldInHeart.getString("PJNAME") : "");
            todo.put("partCodeName", newInHeart.getString("pjname"));
            todo.put("oldUnit", "");
            todo.put("unit", "");
            todo.put("stockQty", newInHeart.getDoubleValue("kcamount"));
            todo.put("untaxPrice", newInHeart.getDoubleValue("xsprice"));
            todo.put("batch", DateUtil.format(new Date(), DateUtil.SHOW_DATE_NUMBER_FORMAT));
            return todo;
        }).collect(Collectors.toList());
        param.put("data", collect);
        SimpleRequest request = new SimpleRequest();
        request.setData(param);
        todoService.inserts(request);
    }

    /***
     * 推送待办
     *  TODO
     */
    private void todo(JSONObject newInHeart, SupplierPlatformItem supplierPlatformItem, String property, JSONObject oldInHeart) {

            JSONObject param = new JSONObject();
            param.put(property, true);
            Map map = MapUtil.mapper(
                    "source", String.valueOf(Math.abs(newInHeart.getIntValue("pjid"))),
                    "supplierPlatformItem", MapUtil.mapper(
                            "id", supplierPlatformItem.getId()
                    ),
                    "oldBrandName", oldInHeart.getString("PJBRAND"),
                    "brandName", newInHeart.getString("pjbrand"),
                    "oldOriginPlace", oldInHeart.getString("PJFACTORY"),
                    "originPlace", newInHeart.getString("pjfactory"),
                    "oldPartCode", oldInHeart.getString("PJCODE"),
                    "partCode", newInHeart.getString("pjcode"),
                    "oldPartCodeName", oldInHeart.getString("PJCODE"),
                    "partCodeName", newInHeart.getString("pjname"),
                    "oldUnit", "",
                    "unit", "",
                    "stockQty", newInHeart.getDoubleValue("kcamount"),
                    "untaxPrice", newInHeart.getDoubleValue("xsprice"),
                    "batch", DateUtil.format(new Date(),DateUtil.SHOW_DATE_NUMBER_FORMAT)
            );
            param.putAll(map);
            SimpleRequest request = new SimpleRequest();
            request.setData(param);
            todoService.insert(request);
    }

    private void jsonToInHeart(JSONObject json, InHeart inHeart) {
        inHeart.setGxcode(json.getString("gxcode"));
        inHeart.setHhcode(json.getString("hhcode"));
        inHeart.setKcamount(json.get("kcamount") != null ? json.getIntValue("kcamount") :0);
        inHeart.setKcdepot(json.getString("kcdepot"));
        inHeart.setKcid(json.get("kcid") != null ? json.getIntValue("kcid"):0);
        inHeart.setPjbrand(json.getString("pjbrand"));
        inHeart.setPjcode(json.getString("pjcode"));
        inHeart.setPjename(json.getString("pjename"));
        inHeart.setPjfactory(json.getString("pjename"));
        inHeart.setPjgensize(json.getString("pjename"));
        inHeart.setPjid(json.get("pjid") != null ? json.getIntValue("pjid") : 0);
        inHeart.setPjname(json.getString("pjname"));
        inHeart.setPjoemcode(json.getString("pjoemcode"));
        inHeart.setPjpp(json.getString("pjpp"));
        inHeart.setPjsize(json.getString("pjsize"));
        inHeart.setPpcode(json.getString("ppcode"));
        inHeart.setXsprice(json.getDoubleValue("xsprice"));
    }

    /***
     * 判断是否重要属性被修改
     */
    private boolean checkImportantUpdate(JSONObject newInHeart, JSONObject oldInHeart) {
        return importantFields.stream().anyMatch(field -> {
            return !checkEqual(newInHeart.getString(field), oldInHeart.getString(field.toUpperCase()));
        });
    }

    /***
     * 用于比较两个字符串是否相等
     */
    private boolean checkEqual(String str, String str1) {
        if (StringUtils.isEmpty(str) && StringUtils.isEmpty(str1)) return true;
        if (str == null || str1 == null) return false;
        return str.equals(str1);
    }

    public void debugging(SimpleRequest request) {
        JSONArray data = request.getJO().getJSONArray("data");
        List<InHeartDebug> list = JSONArray.parseArray(data.toString(), InHeartDebug.class);
        String supplierPlatformItemId = request.getJO().getString("supplierPlatformItemId");
        SupplierPlatformItem supplierPlatformItem = supplierPlatformItemRepository.findOne(supplierPlatformItemId);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setSupplierPlatformItem(supplierPlatformItem);
            list.get(i).setPjid(data.getJSONObject(i).getIntValue("pjid"));
            list.get(i).setId(sequenceService.getId(InHeartDebug.CONST_TABLE_NAME));
        }
        SpringManager.getBean(InHeartDebugRepository.class).save(list);
    }

    public com.apestech.framework.json.JSONObject inHeartData(SimpleRequest request){
        com.apestech.framework.json.JSONObject json = new com.apestech.framework.json.JSONObject();
        try {
            JSONObject jo = request.getJO();
            for (Object condition : jo.getJSONArray("condition")) {
                if ("STATES".equals(JSON.toJSON(condition).getString("field")) && "debugging".equals(JSON.toJSON(condition).getString("value"))) {
                    jo.put("queryid", "supplierPlatformTodo.inHeartDebugData");
                }
            }
            String body = jo.toString();
            json = JSON.toJSON(body);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    private long getHour(String cron){
        CronExpression exp;
        try {
            exp = new CronExpression(cron);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Date startDate = exp.getNextValidTimeAfter(new Date());
        Date endDate = exp.getNextValidTimeAfter(startDate);
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long diff = endDate.getTime() - startDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = ( diff % nd / nh ) + ( day * 24 );
        return hour;
    }
}
